#!/usr/bin/env python
# -*- coding: utf-8 -*-
# $Id: sirun.py 16 2009-07-31 18:04:02Z av1024 $
"""
Subprocess with progressbar wrapper for samizdat.py
"""

#TODO: Rewrite all using multiprocessing istead of popen. Required for py2exe slipstreaming.

import sys
sys.path.append('..')
import os.path
from PyQt4 import QtCore, QtGui
import re
from locale import getpreferredencoding as penc
from sidialogs import progress

class CLIRunner(QtCore.QObject):
	def __init__(self, parent=None):
		QtCore.QObject.__init__(self, parent)

		self.dlg = progress.Progress()
		self.dlg.setModal(True)
		self.prc = QtCore.QProcess()
		self.prc.setProcessChannelMode(QtCore.QProcess.MergedChannels)
		self.prc.setWorkingDirectory( os.path.normpath( os.path.join(os.path.dirname(__file__), '..')))
		self.prc.closeWriteChannel()

		self.do_quit = False

		self._cmd = re.compile(u'PROGRESS\s(?P<level>\d+):\s\[(?P<percent>\d*)\]\s*(?P<msg>.*)', re.I | re.U)

		self.connect(self.dlg, QtCore.SIGNAL('rejected()'), self.onCancel)
		self.connect(self.prc, QtCore.SIGNAL('finished(int)'), self.onFinished)
		self.connect(self.prc, QtCore.SIGNAL('readyReadStandardOutput()'), self.onText)

	def _getwd(self):
		return self.prc.workingDirectory()

	def _setwd(self, value):
		self.prc.setWorkingDirectory(value)

	workdir=property(fget=_getwd, fset=_setwd, doc="Working directory. Should be set to path of samizdat.py")

	@property
	def isRunning(self):
		return self.prc and self.prc.state() != QtCore.QProcess.NotRunning

	def run(self, python_name, args, showProgress=True):
		"""
		Start process if not running.
		pythin_name: name of python interpreter
		args: list with script and arguments to be executed
		"""
		if self.prc.state() == QtCore.QProcess.NotRunning:
			if showProgress and self.dlg:
				self.dlg.show()
				self.dlg.center()
			self.prc.start(python_name, args, QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text) # QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text

	def onCancel(self):
		if self.prc:
			if self.prc.state() != QtCore.QProcess.NotRunning:
				self.prc.kill()
			self.do_quit = True
			if self.dlg:
				self.dlg.close()

	def onFinished(self, retcode):
		"""
		Change cancel/quit button text
		"""
		bb = self.prc.bytesAvailable() if self.prc else 0
		if self.dlg and bb==0:
			self.dlg.cancel2exit()

	def onText(self):
		"""
		Process console text events
		"""
		if not self.prc or not self.dlg: return

		while self.prc.canReadLine() and not self.do_quit:
			QtGui.qApp.processEvents()
			s = unicode(str(self.prc.readLine()).strip(), penc())
			if s.startswith(u'PROGRESS'):
				r = self._cmd.search(s)
				if r:
					a,b,c = r.groups()[0], r.groups()[1],r.groups()[2]
					try:
						b = int(b)
					except:
						b = None
					if a == u'1':
						self.dlg.progress1(c, b)
						if not b and c and c.strip(): self.dlg.progress3(c.strip())
					elif a == u'2': self.dlg.progress2(c, b)
					elif a == u'3': self.dlg.progress3(c)
				QtGui.qApp.processEvents()
			else:
				self.dlg.progress3(s)

		if self.prc.state() == QtCore.QProcess.NotRunning:
			if self.dlg: self.dlg.cancel2exit()
			QtGui.qApp.processEvents()

def check_inet(cli_name='samizdat.py'):
	"""

	"""
	try:
		p = QtCore.QProcess()
		p.setProcessChannelMode(QtCore.QProcess.MergedChannels)
		p.setWorkingDirectory( os.path.normpath( os.path.join(os.path.dirname(__file__), '..')))
		p.closeWriteChannel()
		p.start('python', [cli_name, '--check-inet-only', '--log-level=WARNING'])
		if p.waitForFinished(10000):
			if p.exitCode() == 0:
				return True
	except:
		pass
	return False


if __name__ == "__main__":
	app = QtGui.QApplication([])

	# inet
	print "Check_inet: %s" % (check_inet(),)

	args = ['samizdat.py', '--progress']
	obj = CLIRunner()
	obj.run('python', args)

	app.exec_()
